#include "StdAfx.h"
#include "TerrainBlockChunkItem.h"

#include "ChunkSpace.h"
#include "ChunkManager.h"
#include "Chunk.h"
#include "ChunkFileSerializer.h"

#include "TerrainSerializer.h"

/*
#include <Common/Base/hkBase.h>

// Physics
#include <Physics/Dynamics/World/hkpWorld.h>
#include <Physics/Collide/Dispatch/hkpAgentRegisterUtil.h>
#include <Physics/Dynamics/Entity/hkpRigidBody.h>
*/

using namespace ChunkSystem;
using namespace Common;
using namespace TerrainSystem;

TerrainBlockChunkItem::TerrainBlockChunkItem( const String& strResId, Chunk* pOwnerChunk )
	:ChunkItem(strResId, pOwnerChunk ),m_pOwnerChunk(pOwnerChunk),m_pTerrainInstance( new Terrain )
{
	
}

TerrainBlockChunkItem::~TerrainBlockChunkItem(void)
{
	this->Unload();
}

Terrain* TerrainBlockChunkItem::GetTerrainInstance(void) const
{
	return m_pTerrainInstance;
}

bool TerrainBlockChunkItem::Load( TiXmlElement* pChunkData )
{
	if( pChunkData == NULL || m_pTerrainInstance == NULL )
		return false;
	//get resource path
	assert( strcmp( pChunkData->Value(), "terrain" ) == 0 && pChunkData->FirstChildElement("resource") != NULL );

	String strTerrainPath;
	std::stringstream ss;
	String strTerResPath = pChunkData->FirstChildElement("resource")->GetText();

	ss << ChunkManager::GetInstance().GetResPath() << "/" << ChunkManager::GetInstance().GetSpacePath() << "/" << strTerResPath;
	ss >> strTerrainPath;

	String strFmt = strTerrainPath.substr( strTerrainPath.length() - 3, 3 );
	if( strFmt == "ter" )
	{
		if( !TerrainSerializer::ImportTer( m_pTerrainInstance, strTerrainPath.c_str() ) )
		{
			//assert(!("loading failed."));
			return false;
		}
	}
	else if( strFmt == "tga" )
	{
		if( !TerrainSerializer::ImportTga( m_pTerrainInstance, strTerrainPath.c_str() ) )
		{
			assert(!("loading failed."));
			return false;
		}
	}
	else
	{
		assert(!("Unsupported terrain format."));
		return false;
	}
	
	int iXMark = strTerResPath.find( "_x", 0 );
	int iYMark = strTerResPath.find( "_y", 0 );
	int iDotMark = strTerResPath.find( ".ter", 0 );

	if( iXMark == -1 || iYMark == -1 )
	{
		assert(!("Unsupported terrain format."));
	}

	String strXCoord = strTerResPath.substr( iXMark + 2, iYMark - iXMark - 2 );
	String strYCoord = strTerResPath.substr( iYMark + 2, iDotMark - iYMark - 2 );

	ss.clear();
	int iPosX = 0;
	int iPosY = 0;

	ss << strXCoord;
	ss >> iPosX;
	ss.clear();

	ss << strYCoord;
	ss >> iPosY;
	ss.clear();

	if( m_pOwnerChunk == NULL || m_pOwnerChunk->GetOwnerSpace() == NULL )
		return false;

	Vector3 vStartPos(Vector3::ZERO);
	vStartPos.x = m_pOwnerChunk->GetOwnerSpace()->GetGridResolution() * iPosX;
	vStartPos.z = m_pOwnerChunk->GetOwnerSpace()->GetGridResolution() * iPosY;

	m_pTerrainInstance->SetStartPos( vStartPos );

	ChunkSpace* pSpace = ChunkManager::GetInstance().GetCurChunkSpace();
	if( pSpace == NULL )
		return false;
	float fGridResolution = pSpace->GetGridResolution();
	float fUnitSize = m_pTerrainInstance->GetUnitSize();
	uint16 uWidth = 0 ;
	uint16 uHeight = 0 ;
	m_pTerrainInstance->GetExtent(uWidth, uHeight);

	//and now the width is equal to height
	float fScaledUnitSize = fGridResolution / uWidth;
	float fScaledHeight   = fGridResolution / ( uWidth * fUnitSize );

	m_pTerrainInstance->SetScale( Vector3( fScaledUnitSize, fScaledHeight, fScaledUnitSize ) );

	//create visible for testing.
	if( m_pVisible != NULL )
	{
		IRenderer* pRenderer = ChunkManager::GetInstance().GetRenderer();
		assert( pRenderer != NULL );
		m_pVisible->Load( pRenderer );
	}
	return true;
}

void TerrainBlockChunkItem::Unload( void )
{
	if( m_pVisible != NULL )
		m_pVisible->Unload();

	if( m_pTerrainInstance == NULL )
		return;
	/*
	hkpWorld* pPhysicsWorld = ChunkManager::GetInstance().GetCurPhysicsWorld();
	m_pTerrainInstance->DestroyPhysicsShape( pPhysicsWorld );
	*/

	delete m_pTerrainInstance;
	m_pTerrainInstance = NULL;

}

void TerrainBlockChunkItem::UpdateAABB( void )
{
}

bool TerrainBlockChunkItem::InitSync( void )
{
	/*
	hkpWorld* pPhysicsWorld = ChunkManager::GetInstance().GetCurPhysicsWorld();
	if( pPhysicsWorld == NULL || m_pTerrainInstance == NULL )
		return false;

	m_pTerrainInstance->InitPhysicsShape(pPhysicsWorld);
	*/

	return true;
}

void TerrainBlockChunkItem::CreateVisible(IRenderableFactory* pFac)
{
	if( m_pVisible != NULL )
	{
		assert( false );
		return;
	}

	m_pVisible = pFac->Create(this);
}

void TerrainBlockChunkItem::DestoryVisible(void)
{
	if( m_pVisible == NULL )
	{
		assert( false );
		return;
	}

	delete m_pVisible;
	m_pVisible = NULL;
}

void TerrainBlockChunkItem::DrawVisible( IRenderer* pRenderer )
{
	if( m_pVisible != NULL )
		m_pVisible->Draw( pRenderer );
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
String TerrainBlockChunkFactory::GetType(void)
{
	return ChunkFileSerializer::GetTag( ChunkFileSerializer::eTerrain );
}

ChunkItem* TerrainBlockChunkFactory::Create( ChunkItem* pOwner, TiXmlElement* pChunkItemData )
{
	Chunk* pOwnerChunk = static_cast<Chunk*>( pOwner );
	if( pOwnerChunk == NULL )
	{
		assert(!("Invalid owner, should only be a chunk"));
		return false;
	}

	TiXmlHandle ptrTerrainDataSection( pChunkItemData );
	TiXmlElement* pTerrainResNode = ptrTerrainDataSection.FirstChild("resource").ToElement();
	assert( pTerrainResNode != NULL );
	return new TerrainBlockChunkItem( pTerrainResNode->GetText(), pOwnerChunk );
}
